 
/*  readpv.c
    for use by tm40.c
    Stephen D. Anderson --- October 29, 1994

    Primm-ware function to read the process variables.  It will read
    as many as are available up to 4.  The function does the following
    in order:

        Checks whether field instrument exists, searches if not.

        Sets up a window to display up to 4 process variables and 
        their units; and the primary variable current as % of range.

        Calls "ReadLoop" forever until "q" key hit.  Then it
        closes all windows it opened and returns.

    ON ENTRY:  There are no arguments.

    ON EXIT:   Nothing is returned.


    REVISION LOG:
    1.  August 3, 1995:  added line to cause newline in "units" window
        when the PV is "NONE".


*/

#include "tm40.h"
#include "ieee.h"

void readpv()
{
    extern byte search(void);
    extern byte found;
    extern byte addr[];
    extern byte status_wind;

    void ReadLoop(byte, byte);
    byte j;
    byte s[20];
    byte wvalue,wunits;

    /*  need field instr info? */
    if (!found) found = search();
    if (!found) return;

    /*  proceed with function. */
    WpopUp(CNT_HOR,1,20,3,60,2,WHITE|_BLACK,WHITE|_BLACK);
    WputCen("  Hit 'q' key to exit function");
    Wopen(5,10,16,67,2,WHITE|_BLUE,WHITE|_BLUE);
    Wtitle("<<  Process Variables  >>",TTL_CNT,WHITE|_BLUE);
    Wputs("\n                              VALUE       UNITS\n");
    Wputs("\n  1st (primary) variable");
    Wputs("\n  2nd variable\n  3rd variable\n  4th variable");
    Wputs("\n  primary var current");
    wvalue = Wopen(9,40,14,52,5,LGREEN|_BLUE,LGREEN|_BLUE);
    wunits = Wopen(9,53,14,64,5,LGREEN|_BLUE,LGREEN|_BLUE);

    /*  read variables until "q" is entered.  */
    j = 0;
    while (j != 'q') 
    {
        ReadLoop(wvalue,wunits);
        if (KeyEvent()) j = KwGetCh();
    }
    /*  Get rid of all windows and quit.  */
    Wclose(); Wclose(); Wclose(); Wclose(); return;
}

void ReadLoop(byte wvalue, byte wunits)
{
/*
    Function sends HART command 3 (get process variables).  Checks for
    number of received bytes equal to 9, 14, 19, or 24; corresponding to
    1, 2, 3, or 4 variables.  Clears windows and puts variable info into 
    window with handle "wvalue" and units info into window with handle 
    "wunits".  The variables are written with delays in such a way as to 
    make it clear that they are being updated.  Various error conditions 
    will cause ReadLoop to call functions err1 or err.  In the pair of 
    statements 
        if (status1 != 0) err(3); delay(1000);
    the delay is necessary to allow the user to hit "q" to quit.

    ON ENTRY:  wvalue is the window handle for process variable
               numbers, wunits is the window handle for process
               units.

    ON EXIT:    Nothing is returned.
*/

    extern byte status1,status2;
    extern void ieee(byte, byte *, float *);
    extern int hartcmd(byte *, byte, byte *, byte, byte *, byte);
    extern void err(byte);
    extern void err1(byte);
    extern byte addr[];

    int i,j;
    byte s[20];
    byte byte_count;
    byte *prdv;
    byte rdv_data[40]; int rdv;
    byte numb_pv;
#include "units.h"
    float f;

    /*  Send command 3.  */
    rdv = hartcmd(s, 0, rdv_data, 24, addr, 3);
    if (KeyEvent()) return;

    /*  rdv = 1;    */  /*  insert this to test.  */
    /*  command successful?  */
    if ((rdv & 1) != 0)
    {
        /*  not successful.  put up error message. */
        err1(3); return;
    }

    /*  check number received bytes.  should be 9, 14, 19, or 24. */
    byte_count = rdv/256;
    /*  byte_count = 17;  */    /*  insert to test.  */
    if ( !((byte_count == 9) || (byte_count == 14) || 
    (byte_count == 19) || (byte_count == 24)) )
    {
        /*  not correct number. */
        err(3);
        return;
    }

    /*  report any errors. */
    if (status1 != 0) err(3); delay(1000);

    /*  clear windows and delay each new line to show updating. */
    WVclear(wvalue); WVclear(wunits);

    /*  insert to test:
    rdv_data[4] = 
    */

    /*  display available variables.  */
    prdv = &rdv_data[4];    /*  point to 1st var. */
    byte_count -= 4;
    numb_pv = 0;
    while (byte_count)
    {
        delay(20);
    /*  insert this to test for NaN. */
    /*
    rdv_data[5] = 0x7f; rdv_data[6] = 0xa0;
    rdv_data[7] = 0; rdv_data[8] = 0;
    */
        CONVERT_TO_FLOAT(prdv+1, &f);
        WVputf(wvalue,"%8.4g\n", f);
        WVputf(wunits,"%s\n", units[*prdv]);
        byte_count -= 5; ++numb_pv; prdv += 5;
    }
    /*  list remaining variables as not available. */
    while (numb_pv < 4) 
    {
        delay(20);
        WVputs(wvalue, " None\n"); ++numb_pv;
        WVputs(wunits,"\n");
    }
    /*  display pri var current. */
    delay(20);
    CONVERT_TO_FLOAT(rdv_data, &f);
    WVputf(wvalue,"%8.4g\n", f);
    WVputf(wunits,"mA\n");
}

